/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet;

import java.io.IOException;
import java.util.Enumeration;

/**
 * 定义一个通用的,协议无关的servlet.为Web应用编写一个HTTP servlet的时候,
 * 需要将servlet继承的父类指向{@link javax.servlet.http.HttpServlet}.
 *
 * <p><code>GenericServlet</code>扩展了 <code>Servlet</code>
 * 和 <code>ServletConfig</code> 接口中的方法.
 * servlet可以继承自一个通用的、与协议相关的类(例如<code>HttpServlet</code>),
 * 但servlet也可以直接继承自 <code>GenericServlet</code>.
 *
 *<p><code>GenericServlet</code> 简化了servlet应用程序的开发.
 * 它提供了一个简易版的生命周期方法: <code>init</code> 和 <code>destory</code> 方法,
 * 以及 <code>ServletConfig</code> 接口中所提供的方法.同时
 * <code>GenericServlet</code> 还扩展了接口 <code>ServletContext</code>
 * 中的 <code>log</code> 方法.
 * 
 *
 *<p>如果要编写一个简单的servlet,你只需重写抽象方法 <code>service</code> 即可.
 *
 *
 * @author 	Various
 * @version 	$Version$
 *
 *
 *
 */

 
public abstract class GenericServlet 
    implements Servlet, ServletConfig, java.io.Serializable
{

    private transient ServletConfig config;
    

    /**
     *	什么也不做.servlet的所有初始化工作由 <code>init</code> 方法完成.
     */

    public GenericServlet() { }
    
    
    
   /**
     * servlet容器调用此方法,暗示着servlet正在停止服务.参见 {@link Servlet#destroy}.
     */

    public void destroy() {
    }
    
    
    
    /**
     * 返回具有指定名称的初始化参数值的.如果不存在指定的参数名,则返回 <code>null</code>.
     * 参见 {@link ServletConfig#getInitParameter}.
     *
     *<p>方法为快速从 <code>ServletConfig</code> 接口对象中获取指定参数名称的值提供便捷.
     *
     * @param name 		初始化参数的名称			
     *				
     *
     * @return String 		初始化参数的值
     *
     */ 

    public String getInitParameter(String name) {
	return getServletConfig().getInitParameter(name);
    }
    
    

   /**
    * 返回此servlet已编码的所有初始化参数的 <code>String</code> 对象类型的
    * <code>Enumeration</code> 枚举值.
    * 如果servlet没有初始化参数,则返回一个空的
    * <code>Enumeration</code> 枚举值(但不是null).  参见 {@link
    * ServletConfig#getInitParameterNames}.
    *	
    * <p>方法为快速从 <code>ServletConfig</code> 接口对象中获取指定参数名提供便捷.
    *
    *
    * @return Enumeration 	含有servlet初始化参数名称的 
    * 				<code>String</code> 对象类型的 <code>Enumeration</code> 枚举值.
    *
     *			
    */
   
    public Enumeration getInitParameterNames() {
	return getServletConfig().getInitParameterNames();
    }   
    
     
 
     

    /**
     * 返回当前servlet运行环境中{@link ServletConfig}对象的引用.
     *
     * @return ServletConfig  初始化当前servlet的 <code>ServletConfig</code> 对象
     *
     */
    
    public ServletConfig getServletConfig() {
	return config;
    }
    
    
 
    
    /**
     * 返回当前servlet运行环境中的{@link ServletContext}对象的一个引用.
     * 参见 {@link ServletConfig#getServletContext}.
     *
     *<p>方法为快速从当前servlet的 <code>ServletConfig</code> 接口对象中获取context提供便捷.
     *
     * @return ServletContext 由 <code>init</code> 方法传递到当前servlet的那个
     * <code>ServletContext</code> 对象
     *
     */

    public ServletContext getServletContext() {
	return getServletConfig().getServletContext();
    }



 

    /**
     * 返回与Sevlet相关的信息,例如作者、版本、版权...
     * 默认情况下,方法返回一个空字符串.可以重写此方法让它返回一个有意义的值.
     * 参见 {@link Servlet#getServletInfo}.
     * 
     * @return String 与当前servlet相关的信息,缺省值为空字符串.
     * 
     *
     */
    
    public String getServletInfo() {
	return "";
    }




    /**
     *
     * servlet容器调用此方法,暗示着servlet正在装载服务.参见 {@link Servlet#init}.
     *
     *实现类将会从servlet容器中获得的 {@link ServletConfig}
     *对象并将其存储起来,以便稍后使用.当重载这种类型的方法时,只需
     *<code>super.init(config)</code> 即可.
     *
     * @param config 	包含当前servlet配置信息的 <code>ServletConfig</code> 对象	
     *
     * @exception ServletException 如果异常的产生妨碍了servlet的正常操作.
     *
     * 
     * @see 				UnavailableException
     *
     */

    public void init(ServletConfig config) throws ServletException {
	this.config = config;
	this.init();
    }





    /**
     *	重写此方法后就不需要再调用<code>super.init(config)</code>了.<br/>
     *
     * 	相对于{@link #init(ServletConfig)}来说,只需简单的重写此方法即可.方法本身将会被 
	 * <code>GerericServlet.init(ServletConfig config)</code> 自动调用.
     *  而<code>ServletConfig</code>接口对象仍然可以通过{@link #getServletConfig}获得. 
     *
     * @exception ServletException 	如果异常的产生妨碍了servlet的正常操作.
     *
     */
    
    public void init() throws ServletException {

    }




    /**
     * 将指定信息写入servlet的日志文件中,视servlet名而定(prepended by the servlet's name),
     * 参见{@link ServletContext#log(String)}.
     *
     * @param msg 	写入日志文件的信息
     * 
     */
     
    public void log(String msg) {
	getServletContext().log(getServletName() + ": "+ msg);
    }
   
   
   
   
    /**
     * 为写入servlet日志文件中的<code>Throwable</code>异常提供说明性的文字和堆栈调试信息.
     * 视servlet名而定(prepended by the servlet's name).
     * 参见{@link ServletContext#log(String, Throwable)}.
     *
     *
     * @param message 	描述错误/异常的信息
     *
     * @param t		<code>java.lang.Throwable</code> 错误/异常
     * 				
     */
   
    public void log(String message, Throwable t) {
	getServletContext().log(getServletName() + ": " + message, t);
    }
    
    
    
    /**
     * servlet容器调用此方法让servlet响应客户端的请求.参见 {@link Servlet#service}.
     * 
     * <p>方法是抽象的,所以像<code>HttpServlet</code>这样的子类必须重写改方法.
     *
     *
     *
     * @param req 	携带客户端请求描述的<code>ServletRequest</code>对象 
     *			
     *	
     * @param res 	携带servlet返回请求结果的<code>ServletResponse</code>对象 
     *
     * @exception ServletException 	因servlet调用接口方法产生的异常
     *
     *
     * @exception IOException 		如果发生输入或输出错误
     *
     */

    public abstract void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException;
    


    /**
     * 返回当前servlet实例的名称.
     * 参见 {@link ServletConfig#getServletName}.
     *
     * @return   servlet实例的名称
     *
     */

    public String getServletName() {
        return config.getServletName();
    }
}
